package cn.edu.tsinghua.mutimedia.image.extract;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import cn.edu.tsinghua.mutimedia.util.Conf;

import jAudioFeatureExtractor.DataModel;
import jAudioFeatureExtractor.DataTypes.RecordingInfo;

public class Extract {

	/**
	 * @param args
	 * @throws Exception 
	 */
	public static void extract(String[] args) {
		try
		{
			String videofile = "";
			if(args.length > 0)
			{
				videofile = args[0];
			}
			
			String audioFile = videofile+".wav";
			
			String cmd = "ffmpeg -i %s -ar 16000 -ac 1 -f wav -vn -y %s";
			cmd = String.format(cmd, videofile, audioFile);
			openMyExe(cmd);						
			String xmlFile = audioFile.replace(".wav",".xml");
			ExtractModelFromFile(audioFile, xmlFile);
			System.out.println("image.extract*****************************Feature Extracted******************");
			AudioSection [] sectionList = GetAudioSections(xmlFile);
			SmoothNoise(sectionList);
			OutputFile(sectionList,xmlFile.replace(".xml", ".txt"));
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
	
	public static void ExtractModelFromFile(String filePath, String outFile) throws IOException
	{
		String definitionSavePath = filePath+"_definition.xml";
		String valuesSavePath = outFile;
		outFile = valuesSavePath;
		int window_size = 512;
		double window_overlap = 0;
		double sampling_rate = 16000;
		boolean normalise = false;
		RecordingInfo recordingInfo = new RecordingInfo(filePath);
		RecordingInfo [] infoList = new RecordingInfo[]{recordingInfo};
		ExtractListener listener = new ExtractListener();
		DataModel dataModel = new DataModel(Conf.LOCAL_VIDEO_DIR+"features.xml",listener);
		
		FileOutputStream values_to = null;
		FileOutputStream definitions_to = null;
		try {
			dataModel.validateFile(definitionSavePath,valuesSavePath);
			File feature_values_save_file = new File(valuesSavePath);
			File feature_definitions_save_file = new File(definitionSavePath);
			// Prepare stream writers
			values_to = new FileOutputStream(feature_values_save_file);
			definitions_to = new FileOutputStream(feature_definitions_save_file);

			dataModel.featureKey = definitions_to;
			dataModel.featureValue = values_to;
			for(int i=0; i<dataModel.defaults.length; i++)
			{
				dataModel.defaults[i] = i==89;
				
			}
			dataModel.extract(window_size, window_overlap,
					sampling_rate,
					normalise, true, true,
					infoList, 0);
			
		} 
		catch (Exception e)
		{
			e.printStackTrace();
		}
		finally
		{
			if(values_to != null)
				values_to.close();
			if(definitions_to != null)
				definitions_to.close();
		}
	}
	
	public static AudioSection [] GetAudioSections(String file)
	{
		AudioSection [] audioList = null;
		Document doc=null;
	    try{
	      
		   DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
		   DocumentBuilder db=dbf.newDocumentBuilder();
		   doc=db.parse(file);
		   NodeList proNList=doc.getElementsByTagName("section");
		   Element proEle;
		   audioList = new AudioSection[proNList.getLength()];
		   for(int i = 0; i < proNList.getLength(); i++)
		   {
			   AudioSection section = new AudioSection();
			   proEle = (Element)proNList.item(i);
			   section.start = proEle.getAttribute("start");
			   section.stop = proEle.getAttribute("stop");
			   section.values = new double[13];
			   Element featureNode = (Element)proEle.getElementsByTagName("feature").item(0);
			   NodeList childNodes = featureNode.getElementsByTagName("v");
			   for(int j=0; j < childNodes.getLength(); j++)
			   {
				   Node node = childNodes.item(j);
				   double val = Double.parseDouble(node.getFirstChild().getNodeValue());
				   section.values[j] = val;
				   
			   }
			   audioList[i] = section;
		   }
	    }
	    catch(Exception ex){
		      ex.printStackTrace();
		}
		return audioList;
	}
	
	public static AudioSection [] SmoothNoise(AudioSection [] sectionList)
	{
		int sectionLength = sectionList.length;
		AudioSection [] newSectionList = new AudioSection [sectionLength];
		for(int i=0; i < sectionLength; i++)
		{
			int t = i;
			int t_1 = t-1 >= 0 ? t-1 : t;
			int t_2 = t-2 >= 0 ? t-2 : t;
			int t_3 = t+1 >= sectionLength ? t : t+1;
			int t_4 = t+2 >= sectionLength ? t : t+2;
			AudioSection section = new AudioSection();
			section.start = sectionList[t].start;
			section.stop = sectionList[t].stop;
			section.values = new double[13];
			newSectionList[i] = section;
			for(int j=1; j < section.values.length; j++)
			{
				section.values[j] = sectionList[t].values[j] + 2 * sectionList[t_4].values[j] + sectionList[t_3].values[j] -sectionList[t_1].values[j] -2 * sectionList[t_2].values[j];
			}
		}
		return newSectionList;
		
	}
	
	public static void OutputFile(AudioSection [] sectionList, String file)
	{
		 try 
		 {
			 File f = new File(file);
			 if (f.exists()) 
			 {
				 System.out.println("文件存在");
			 } 
			 else 
			 {
				 System.out.println("文件不存在，正在创建...");
				 if (f.createNewFile()) 
				 {
					 System.out.println("文件创建成功！");
				 }
				 else 
				 {
					 System.out.println("文件创建失败！");
				 }
			 }
	       
			 BufferedWriter output = new BufferedWriter(new FileWriter(f));
			 for(int i=0; i < sectionList.length; i++)
			 {
				 output.write(sectionList[i].toString());
			 }
	       
			 output.close();
	      } 
		 catch (Exception e) 
		 {
		       e.printStackTrace();
		 }
	}
	
    public static void openMyExe(String execmd) {  
       Runtime rn = Runtime.getRuntime();  
       Process p = null;  
       try {  
           p = rn.exec(execmd); 
           InputStream is = p.getInputStream();
           BufferedReader reader = new BufferedReader(new InputStreamReader(is));
           String line;
           while((line=reader.readLine())!=null)
           {System.out.println(line);};
           p.waitFor();
           is.close();
           reader.close();
           p.destroy();
           System.out.println("Audio Extracted");
           
       } catch (Exception e) {  
           System.out.println("Error my exec ");  
       }  
    }  
	
	
	

}


